# Copyright (c) 2018 Presto Labs Pte. Ltd.
# Author: xguo

import functools

from coin.exchange.base.kr_rest.product import NativeProduct, NormProduct
from coin.exchange.kraken.kr_rest.constants import (native_quote_currency_list,
                                                    native_currency_list,
                                                    currency_list,
                                                    clean_symbol_list)
from coin.exchange.kraken.kr_rest.currency import KrakenCurrency


# Native symbols end with ".d" are not handled.
@functools.lru_cache(maxsize=256)
def parse_rest_native_symbol(native_symbol):
  assert len(native_symbol) <= 8, \
      'Invalid native symbol name. %s\n' % native_symbol
  altname_map = dict(native_currency_list)

  if len(native_symbol) in [6, 7]:
    for quote in native_quote_currency_list:
      quote = altname_map[quote]
      if native_symbol.endswith(quote):
        base = native_symbol.replace(quote, '')
        assert base in altname_map.values()
        return KrakenCurrency.FromStrNativeCurrency(base), KrakenCurrency.FromStrNativeCurrency(
            quote)
  elif len(native_symbol) == 8:
    for quote in native_quote_currency_list:
      if native_symbol.endswith(quote):
        base = native_symbol.replace(quote, '')
        assert base in altname_map.keys(), ('Invalide native symbol for Kraken: %s' % native_symbol)
        base = altname_map[base]
        quote = altname_map[quote]
        return KrakenCurrency.FromStrNativeCurrency(base), KrakenCurrency.FromStrNativeCurrency(
            quote)
  raise ValueError('Invalide native symbol for Kraken: %s' % native_symbol)


@functools.lru_cache(maxsize=256)
def parse_ws_native_symbol(native_symbol):
  base, quote = native_symbol.split('/')
  return KrakenCurrency.FromStrNativeCurrency(base), KrakenCurrency.FromStrNativeCurrency(quote)


@functools.lru_cache(maxsize=256)
def parse_native_symbol(native_symbol):
  if '/' in native_symbol:
    return parse_ws_native_symbol(native_symbol)
  else:
    return parse_rest_native_symbol(native_symbol)


@functools.lru_cache(maxsize=256)
def remove_xz_from_rest_native_symbol(native_symbol):
  base, quote = parse_rest_native_symbol(native_symbol)
  return "%s%s" % (base.native_currency, quote.native_currency)


# !!! Currently this product class does not handle symbols ends with ".d"
class KrakenProduct(NativeProduct):
  _exchange = "Kraken"
  NativeCurrencyType = KrakenCurrency

  def __init__(self, base, quote):
    assert base != quote, (base, quote)
    rest_native_symbol = "%s%s" % (base.native_currency, quote.native_currency)
    self._ws_native_symbol = "%s/%s" % (base.native_currency, quote.native_currency)

    super().__init__(base, quote, rest_native_symbol)
    self._native_subscription_symbol = \
        '%s/%s' % (base.native_currency, quote.native_currency)

  def rest_native_symbol(self):
    return self.native_symbol

  def ws_native_symbol(self):
    return self._ws_native_symbol

  @classmethod
  def FromStrNativeProductImpl(cls, product, current_datetime):
    assert isinstance(product, str), type(product)
    if '/' not in product:
      assert product in clean_symbol_list, product
    base, quote = parse_native_symbol(product)
    return KrakenProduct(base, quote)
